/*******************************************************************************
 * Copyright (c) 2010 NineConsult A/S (http://nine.dk) and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/

package dk.nineconsult.jmoller.mapr.validation;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;

import org.eclipse.xtext.common.types.JvmFeature;
import org.eclipse.xtext.util.Strings;
import org.eclipse.xtext.validation.Check;

import com.google.inject.Inject;

import dk.nineconsult.jmoller.mapr.mapr.FeatureMap;
import dk.nineconsult.jmoller.mapr.mapr.Mapping;
import dk.nineconsult.jmoller.mapr.mapr.MaprPackage;
import dk.nineconsult.jmoller.mapr.scoping.IBeanPatternFeatureLookup;
 
public class MaprJavaValidator extends AbstractMaprJavaValidator {

	@Inject
	private IBeanPatternFeatureLookup featureLookup;

	// CHANGED: Introspect left-hand sides and check for mapping completeness
	@Check
	public void checkLeftSides(Mapping mapping) {
		Map<String, JvmFeature> features = featureLookup.getBeanPatternFeatures(mapping.getLeftClass());
		
		Set<String> missing = new HashSet<String>(features.keySet());
		for (FeatureMap fm : mapping.getMappedFeatures()) {
			JvmFeature leftField = fm.getLeftField();
			if (leftField != null) {
				String featureName = featureLookup.getSimpleName(leftField);
				if (!missing.remove(featureName)) {
					error("Surplus specifications for '" + featureName + "' (left side)", fm, MaprPackage.FEATURE_MAP__LEFT_FIELD);				
				}
			}
		}
		if (! missing.isEmpty() && mapping.getCoverage().equals("complete")) {
			error("No specifications for left side features: " + Strings.concat(", ", new LinkedList<String>(missing)), mapping, MaprPackage.MAPPING__COVERAGE);
		}
	}

	// CHANGED: Introspect right-hand sides and check for mapping completeness
	@Check
	public void checkRightSides(Mapping mapping) {
		Map<String, JvmFeature> features = featureLookup.getBeanPatternFeatures(mapping.getRightClass());
		
		Set<String> missing = new HashSet<String>(features.keySet());
		for (FeatureMap fm : mapping.getMappedFeatures()) {
			JvmFeature rightField = fm.getRightField();
			if (rightField != null) {
				String featureName = featureLookup.getSimpleName(rightField);
				if (!missing.remove(featureName)) {
					error("Surplus specifications for '" + featureName + "' (light side)", fm, MaprPackage.FEATURE_MAP__RIGHT_FIELD);				
				}
			}
		}
		if (! missing.isEmpty() && mapping.getCoverage().equals("complete")) {
			error("No specifications for right side features: " + Strings.concat(", ", new LinkedList<String>(missing)), mapping, MaprPackage.MAPPING__COVERAGE);
		}
	}

	public void setFeatureLookup(IBeanPatternFeatureLookup featureLookup) {
		this.featureLookup = featureLookup;
	}

	public IBeanPatternFeatureLookup getFeatureLookup() {
		return featureLookup;
	}
}
